package org.opu.pc.sg;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.opu.pc.util.IOSafeUtils;

/**
 *
 * @author Yuriy Dunko
 */
public abstract class AbstractStatementGenerator {

    public static final String DOCUMENT_PATH = "word/document.xml";

    public static final String BEGIN_YEAR_VAR = "year1";
    public static final String END_YEAR_VAR = "year2";

    /**
     * Statement generation properties - simples fields in document that should
     * be replaced
     */
    protected Properties sgProperties = new Properties();
    
    /**
     * Data for generation statement.
     * For example it can be year, or some specific object ...
     */
    protected Map<String, Object> variables = new HashMap<String, Object>();

    public void resetSGProperties(String classPath) throws IOException{
        resetSGProperties();
        if (classPath != null && !classPath.isEmpty()){
            sgProperties.load(IOSafeUtils.getResourceAsStream(classPath));
        }
    }

    public void resetSGProperties(){
        sgProperties.clear();
    }

    public void setSGProperty(String name, String value){
        sgProperties.setProperty(name, value);
    }

    public void resetVariables(){
        variables.clear();
    }

    public void addVariable(String name, Object value){
        variables.put(name, value);
    }

    public byte[] generateDocument() throws IOException{
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        packDOCXArchive(getDocument(), bout, getTemplate());
        return bout.toByteArray();
    }

    protected abstract String getDocument() throws IOException ;

    protected abstract String getTemplatePath();

    protected final InputStream getTemplate() throws IOException {
        return IOSafeUtils.getResourceAsStream(getTemplatePath());
    }

    /**
     * Open "template" input stream as archive, read from there all entries
     * and write it to output stream. Then added the document part. <br>
     * <b>NOTE:</b> <u>All streams will be closed after this method work</u>
     */
    protected void packDOCXArchive(String document, OutputStream out,
            InputStream template) throws IOException {

        ZipOutputStream zout = new ZipOutputStream(out);
        ZipInputStream zis = new ZipInputStream(template);
        ZipEntry ze;

        while ((ze = zis.getNextEntry()) != null) {
            String name = ze.getName();
            zout.putNextEntry(new ZipEntry(name));
            
            if (DOCUMENT_PATH.equals(name)){
                IOUtils.copy(new ByteArrayInputStream(document.getBytes("UTF-8")), zout);
            } else {
                IOUtils.copy(zis, zout);
            }

            zis.closeEntry();
        }

        zis.close();
        template.close();
        zout.close();
        out.close();
    }
}
